//import { Logger } from 'log4js/lib/logger';

//import { ENGINE_METHOD_ALL } from 'constants';

//import { init } from '../utils/db';

//import { join } from 'path';

'use strict';

var WebSocketServer = require('ws').Server;
var util = require('../utils/util');
var c = require('../majiang_server/config.json');
var c_enmeys = require('../majiang_server/enemysConfig.json');
var c_position = require('../majiang_server/positionConfig.json');
var crypto = require('../utils/crypto');
//用来管理房间

//用来管理玩家
var userMgr = require("./usermgr");
var fightRoomMgr = require("./fightRoommgr");

var AwesomeMessage = require('./protobuf/awesome.js').AwesomeMessage;
var c2sLogin = require('./protobuf/awesome.js').c2sLogin;
var s2cLogin = require('./protobuf/awesome.js').s2cLogin;
var c2sReady = require('./protobuf/awesome.js').c2sReady;
var s2cReady = require('./protobuf/awesome.js').s2cReady;
var s2cGameStart = require('./protobuf/awesome.js').s2cGameStart;
var s2cRoundEnd = require('./protobuf/awesome.js').s2cRoundEnd;
var c2sSendEnemy = require('./protobuf/awesome.js').c2sSendEnemy;
var s2cSendEnemy = require('./protobuf/awesome.js').s2cSendEnemy;
var c2sGameover = require('./protobuf/awesome.js').c2sGameover;
var s2cGameover = require('./protobuf/awesome.js').s2cGameover;
var c2sleakEnemy = require('./protobuf/awesome.js').c2sleakEnemy;
var s2cleakEnemy = require('./protobuf/awesome.js').s2cleakEnemy;
var c2sskill = require('./protobuf/awesome.js').c2sskill;
var s2cskill = require('./protobuf/awesome.js').s2cskill;
var enmeys = require('./protobuf/awesome.js').enmeys;
var location = require('./protobuf/awesome.js').location;
var s2cgetGold = require('./protobuf/awesome.js').s2cgetGold;
var c2stoNext = require('./protobuf/awesome.js').c2stoNext;
var s2ctoNext = require('./protobuf/awesome.js').s2ctoNext;
var c2sInviteMID = require('./protobuf/awesome.js').c2sinvite;


//需要检测一下玩家是否在线，需要检测一下房间内玩家是否失去连接，
/**日志打印 */
//var logFile = require('./logmgr').logger('log_file');
//var logData = require('./logmgr').logger('log_date');
//var logError = require('./logmgr').logger('log_error');

var users = [];

var userid = 33;
var userState = {
    idle: 0,
    ready: 1,
    fight: 2,
    build: 3,
    leave: 4,
    invite: 5,
};

var heartCount = 0;

var c = require('../majiang_server/config.json');
/**用来表示玩家的状态， */
var messageEnum = {
    C2SloginMID: 1001,
    S2CloginMID: 1101,
    c2sReadyMID: 1002,
    s2cReadyMID: 1102,
    s2cGameStartMID: 1103,
    s2cRoundEndMID: 1104,
    c2sSendEnemy: 1005,
    s2cSendEnemyMID: 1105,
    c2sGameoverMID: 1006,
    s2cGameoverMID: 1106,
    c2sleakEnemyMID: 1007,
    s2cleakEnemyMID: 1107,
    c2sskillMID: 1008,
    s2cskillMID: 1108,
    s2cgetGoldMID: 1109,
    c2sToNextMID: 1010,
    s2cToNextMID: 1110,
    c2sInviteMID: 1011,
    ping: 50,
    pong: 51,
    ready: 1,
    fight: 2,
    build: 3,
};

/** 房间时间 */
var startRoomTime = -1;
exports.start = function ($config) {
    /**日志测试 */


    var config = $config;
    var wss = new WebSocketServer({ port: config.CLIENT_PORT });

    setInterval(gameloop, c.roomTime);


    var heartMessage = AwesomeMessage.encode(AwesomeMessage.create({ meesageId: messageEnum.ping })).finish();

    /**更新房间内时间 */

    /**
     * 需要一个专门的定时器来判断，是否要重开房间
     */


    exports.ping = function () {
        wss.clients.forEach(function each(ws) {
            var user = userMgr.get(ws.userId);
            if (user != null) {
                var enmey = userMgr.get(user.fightUserId);
                if (enmey != null && !enmey.isLink) {
                    if (enmey.userState == userState.ready) {
                        fightRoomMgr.ExitWaitingRoom(enmey);
                        console.log("kick ready user" + enmey.userId);
                    }
                    else if (enmey.userState == userState.fight) {
                        console.log("kick fight user" + enmey.userId);
                        fightRoomMgr.ExitFightingRoom(enmey);

                        var buf = send_client_message(s2cGameover, { whoWin: 1, noLink: 1 }, messageEnum.s2cGameoverMID);
                        if (user && user.socket) {
                            user.userState = userState.leave;
                            exports.sendProbufMessage(user.socket, buf);
                        }
                    }
                    else {
                        console.log("kick user" + enmey.name);
                    }
                    //user.userState = userState.leave;
                    userMgr.kickUser(enmey);
                }
                //return ws.terminate();  
            }
            exports.sendProbufMessage(ws, heartMessage);

        });
    }
    console.log("game server is listening on " + config.CLIENT_PORT);
    wss.on('connection', function connection(ws) {
        //  console.log('[INFO] Playerid ' + ws.id + " Connecting...");
        // var position = c.newPlayerInitialPosition == 'farthest' ? util.uniformPosition(users, 20) : util.randomPosition(20);

        // var currentPlayer = {
        //     id: ws.id,
        //     //用来保存玩家的信息
        //     userID: -1,
        //     roomId: 0,
        //     x: position.x,
        //     y: position.y,
        //     frogType: 2,
        //     level: 4,
        //     type: "player",

        //     lastHeartbeat: new Date().getTime(),
        //     speed: 0,

        // };
        // var data={
        //     account:ws.id,

        // };
        // userMgr.createPlayer();
        // ws.send(JSON.stringify({"cmdName":"welcome","data":c.maxGameTime*60}));

        //  const buf5 = Buffer.from(JSON.stringify({ "cmdName": "playerLogin", "data": {}  }));
        //  ws.send(buf5);
        //   var str=JSON.stringify({ "cmdName": "playerLogin", "data": {} });

        //     exports.sendBitMessage(ws, JSON.stringify({ "cmdName": "playerLogin", "data": {} }));
        /**
         * gotit：玩家进入游戏
         * windowResized：玩家窗口尺寸
         * changeType：改变玩家类型
         * respawn：重生  用于死亡和再次进入游戏
         * exitRoom：玩家离开房间 暂没用到
         * 0：玩家操作
         */


        ws.on('message', function incoming(message) {
            //  var mss=zip.compressions.DEFLATE.uncompress();

            //    var MessageData = JSON.parse(message.toString());
            // /**玩家登陆 */
            var tt = AwesomeMessage.decode(message);

            //登陆战斗服务器
            if (tt.meesageId == messageEnum.C2SloginMID) {
                var tmpMessage = c2sLogin.decode(tt.data);
                if (check_account(tmpMessage)) {
                    /**解析飞机json */
                    var enmeys_json = c_enmeys;
                    var enmeys_config = [];
                    for (let i = 0; i < enmeys_json.length; i++) {
                        var enmeys_class = {
                            type: enmeys_json[i].type,
                            hp: enmeys_json[i].hp,
                            price: enmeys_json[i].price,
                            speed: enmeys_json[i].speed,
                            getGold: enmeys_json[i].getGold,
                            cd: enmeys_json[i].cd
                        }
                        enmeys_config.push(enmeys_class);
                    }
                    var s2cLoginData = {
                        userID: userid,
                        errorCode: 0,
                        enmeysConfig: enmeys_config
                    }
                    //需要根据玩家的信息，创建一个新的玩家，包括玩家的名字，以及其他信息
                    if (tmpMessage.account != "success") {
                        console.log('create ' + tmpMessage.account);
                        userMgr.createPlayer(tmpMessage, ws, userid);
                        userid++;
                    } else {
                        userMgr.get(tmpMessage.userId).userState = userState.idle;
                        s2cLoginData.userID = tmpMessage.userId;
                        console.log(tmpMessage.userId + "进入联机大厅");
                    }

                    var bufEnter = exports.changeType(s2cLogin, s2cLoginData);
                    var payload = { meesageId: messageEnum.S2CloginMID, data: bufEnter };
                    var errMsg = AwesomeMessage.verify(payload);
                    if (errMsg)
                        throw Error(errMsg);
                    // Create a new message
                    var message = AwesomeMessage.create(payload);
                    var buf = AwesomeMessage.encode(message).finish();
                    exports.sendProbufMessage(ws, buf);
                    return;
                }
                else {
                    var s2cLoginData = {
                        userID: userid,
                        errorCode: 33
                    }
                    var bufEnter = exports.changeType(s2cLogin, s2cLoginData);
                    var payload = { meesageId: messageEnum.S2CloginMID, data: bufEnter };
                    var errMsg = AwesomeMessage.verify(payload);
                    if (errMsg)
                        throw Error(errMsg);
                    var message = AwesomeMessage.create(payload);
                    var buf = AwesomeMessage.encode(message).finish();
                    exports.sendProbufMessage(ws, buf);
                    return;
                }
            }
            //准备匹配
            if (tt.meesageId == messageEnum.c2sReadyMID) {
                var tmpMessage = c2sReady.decode(tt.data);
                var user = userMgr.get(tmpMessage.userID);

                var errorcodeTmp = 0;
                if (user == null) {
                    errorcodeTmp = 5;
                }
                else {
                    errorcodeTmp = fightRoomMgr.EnterWaitingRoom(user);
                }
                var s2cReadyData = {
                    errorCode: errorcodeTmp,
                    userID: tmpMessage.userID,
                }
                var bufEnter = exports.changeType(s2cReady, s2cReadyData);
                var payload = { meesageId: messageEnum.s2cReadyMID, data: bufEnter };
                var errMsg = AwesomeMessage.verify(payload);
                if (errMsg)
                    throw Error(errMsg);
                var message = AwesomeMessage.create(payload);
                var buf = AwesomeMessage.encode(message).finish();
                exports.sendProbufMessage(ws, buf);
                return;
            }
            //邀请好友
            if (tt.meesageId == messageEnum.c2sInviteMID) {
                var tmpMessage = c2sInviteMID.decode(tt.data);
                var user = userMgr.get(tmpMessage.userId);
                var errorcodeTmp = 0;
                if (user == null) {
                    errorcodeTmp = 5;
                }
                else {
                    user.invitation = tmpMessage.invitation;
                    console.log(user.userId + "玩家接收邀请函为" + user.invitation);
                    errorcodeTmp = fightRoomMgr.enterInvitingRoom(user);
                }
                var s2cReadyData = {
                    errorCode: errorcodeTmp,
                    userID: tmpMessage.userId,
                }
                var bufEnter = exports.changeType(s2cReady, s2cReadyData);
                var payload = { meesageId: messageEnum.s2cReadyMID, data: bufEnter };
                var errMsg = AwesomeMessage.verify(payload);
                if (errMsg)
                    throw Error(errMsg);
                var message = AwesomeMessage.create(payload);
                var buf = AwesomeMessage.encode(message).finish();
                exports.sendProbufMessage(ws, buf);
                return;
            }
            //玩家相互发兵
            if (tt.meesageId == messageEnum.c2sSendEnemy) {
                var tmpMessage = c2sSendEnemy.decode(tt.data);
                var user = userMgr.get(tmpMessage.userId);
                if (user == null) {
                    //console.log("玩家信息错误" + user.userId);
                    return;
                }
                var userfriend = userMgr.get(user.fightUserId);
                if (user == null) {
                    //console.log("玩家信息错误" + userfriend.userId);
                    return;
                }
                //校验是否重复发兵
                if (tmpMessage.Roundnumber == user.roundLevel) {
                    var enmeys = plane_order(tmpMessage.enmeys);
                    var enmeys_position = plane_position(tmpMessage.enmeys);

                    var s2cSendEnemyData = {
                        enmeys: enmeys,
                        enmeysPosition: enmeys_position
                    }
                    var bufEnter = exports.changeType(s2cSendEnemy, s2cSendEnemyData);
                    var payload = { meesageId: messageEnum.s2cSendEnemyMID, data: bufEnter };
                    var errMsg = AwesomeMessage.verify(payload);
                    if (errMsg)
                        throw Error(errMsg);
                    var message = AwesomeMessage.create(payload);
                    var buf = AwesomeMessage.encode(message).finish();
                    if (userfriend && userfriend.socket)
                        exports.sendProbufMessage(userfriend.socket, buf);
                    //校验发兵金币
                    // user.gold = checkGold(user.gold, tmpMessage.gold, enmeys);
                    var s2cgetGoldData = {
                        gold: tmpMessage.gold
                    }
                    var buf_1 = send_client_message(s2cgetGold, s2cgetGoldData, messageEnum.s2cgetGoldMID);
                    if (user && user.socket)
                        exports.sendProbufMessage(user.socket, buf_1);
                    /**存储当前回合可得最大金币--存给对方 */
                    if (userfriend)
                        userfriend.canGetGold = 0;
                    for (let q = 0; q < enmeys.length; q++) {
                        for (let k = 0; k < c_enmeys.length; k++) {
                            if (enmeys[q] == c_enmeys[k].type) {
                                userfriend.canGetGold += c_enmeys[k].getGold;
                                break;
                            }
                        }
                    }
                    return;
                } else {
                    return;
                }
            }

            //游戏购买界面准备结束，进入下一回合
            if (tt.meesageId == messageEnum.c2sToNextMID) {
                let tmpMessage = c2stoNext.decode(tt.data);
                let user = userMgr.get(tmpMessage.userId);
                if (user != null) {
                    user.isReadyToNext = true;
                    let userfriend = userMgr.get(user.fightUserId);
                    if (userfriend != null && userfriend.socket) {
                        let buf = send_client_message(s2ctoNext, { userId: user.userId, isToNext: 1 }, messageEnum.s2cToNextMID);
                        exports.sendProbufMessage(userfriend.socket, buf);
                    }
                }

            }

            /**游戏结束
             * 1-改变两个人的状态
             * 2-发送战斗结果
             * 3-user一定是输的人
             */
            if (tt.meesageId == messageEnum.c2sGameoverMID) {
                var tmpMessage = c2sGameover.decode(tt.data);
                var user = userMgr.get(tmpMessage.userId);
                if (user != null) {
                    var userfriend = userMgr.get(user.fightUserId);
                }
                user.userState = userState.leave;
                userfriend.userState = userState.leave;

                var buf_1 = send_client_message(s2cGameover, { whoWin: 0, noLink: 0 }, messageEnum.s2cGameoverMID);
                if (user && user.socket)
                    exports.sendProbufMessage(user.socket, buf_1);
                var buf_2 = send_client_message(s2cGameover, { whoWin: 1, noLink: 0 }, messageEnum.s2cGameoverMID);
                if (userfriend && userfriend.socket)
                    exports.sendProbufMessage(userfriend.socket, buf_2);

                return;
            }
            //发送对方漏兵
            if (tt.meesageId == messageEnum.c2sleakEnemyMID) {
                var tmpMessage = c2sleakEnemy.decode(tt.data);
                var user = userMgr.get(tmpMessage.userId);
                if (user != null) {
                    var userfriend = userMgr.get(user.fightUserId);
                }
                /**校验获得金币 */
                // user.gold = checkGold_leak(tmpMessage.enmeys, user.canGetGold, tmpMessage.gold, user.gold);
                var s2cgetGoldData = {
                    gold: tmpMessage.gold
                }
                var buf_1 = send_client_message(s2cgetGold, s2cgetGoldData, messageEnum.s2cgetGoldMID);
                if (user && user.socket)
                    exports.sendProbufMessage(user.socket, buf_1);

                /**飞机随机位置 */
                var position_array = plane_position(tmpMessage.enmeys);
                /**飞机顺序 */
                var planes_order = plane_order(tmpMessage.enmeys);
                var s2cleakEnemyData = {
                    userId: user.userId,
                    enmeys: planes_order,
                    enmeysPosition: position_array
                }
                var buf = send_client_message(s2cleakEnemy, s2cleakEnemyData, messageEnum.s2cleakEnemyMID);
                if (user && user.socket)
                    exports.sendProbufMessage(user.socket, buf);
                if (userfriend && userfriend.socket)
                    exports.sendProbufMessage(userfriend.socket, buf);
                return;
            }
            //发送对方技能和堡垒hp
            if (tt.meesageId == messageEnum.c2sskillMID) {
                var tmpMessage = c2sskill.decode(tt.data);
                var user = userMgr.get(tmpMessage.userId);
                if (user != null) {
                    var userfriend = userMgr.get(user.fightUserId);
                }
                if (userfriend == null) {
                    console.log("玩家ID不存在");
                    return;
                }
                var s2cskillData = {
                    type: tmpMessage.type,
                    skill: tmpMessage.skill
                }

                var bufEnter = exports.changeType(s2cskill, s2cskillData);
                var payload = { meesageId: messageEnum.s2cskillMID, data: bufEnter };
                var errMsg = AwesomeMessage.verify(payload);
                if (errMsg)
                    throw Error(errMsg);
                var message = AwesomeMessage.create(payload);
                var buf = AwesomeMessage.encode(message).finish();
                if (userfriend && userfriend.socket)
                    exports.sendProbufMessage(userfriend.socket, buf);
                return;
            }
            if (tt.meesageId == messageEnum.pong) {
                var user = userMgr.get(ws.userId);
                if (user != null) {
                    user.isLink = true;
                }
            }
        });
        ws.on("open", function open() {
            console.log("open");
        })
        ws.on("close", function close() {
            // if (util.findIndex(users, currentPlayer.id) > -1) {
            //     exitRoom(currentPlayer);
            //     users.splice(util.findIndex(users, currentPlayer.id), 1);
            //     delete sockets[currentPlayer.id];
            //     console.log('[INFO] User ' + currentPlayer.name + ' disconnected!');
            // }
        })
        ws.on("error", function error(ww) {
            //  logError.info("error" + ww);
        });
    });

    /*
    * 游戏开始的时候发送其他玩家信息
     * */

    exports.gameStart = function (userID, errorcodet) {

        var user = userMgr.get(userID);
        var errorcode = 0;
        if (user)
            var userfriend = userMgr.get(user.fightUserId);
        if (user == null) {
            console.log("获取玩家失败")
            errorcode = 100;
        }
        else {
            var userOhter = userMgr.get(user.fightUserId)
            if (userOhter == null) {
                console.log("获取对战玩家失败")
                errorcode = 101;
            }
            else {
                errorcode = 0;

            }
        }
        if (errorcode != 0) {
            var s2cGameStartData = {

                errorCode: errorcodet,

            }
        }
        else {
            var s2cGameStartData = {
                //发送的为对方的头像
                errorCode: errorcodet,
                headimg: userfriend.headimg,
                name: userfriend.name,
                sex: userfriend.sex
            }
        }
        var bufEnter = exports.changeType(s2cGameStart, s2cGameStartData);
        var payload = { meesageId: messageEnum.s2cGameStartMID, data: bufEnter };
        var errMsg = AwesomeMessage.verify(payload);
        if (errMsg)
            throw Error(errMsg);
        var message = AwesomeMessage.create(payload);
        var buf = AwesomeMessage.encode(message).finish();
        if (user && user.socket)
            exports.sendProbufMessage(user.socket, buf);

    }
    /**30秒发一次战斗请求 */
    exports.Combatrequest = function (userID, errorcodet) {
        var user = userMgr.get(userID);
        var errorcode = 0;
        if (user == null) {
            console.log("获取玩家失败")
            errorcode = 100;
        }
        else {
            var userOhter = userMgr.get(user.fightUserId)
            if (userOhter == null) {
                console.log("获取对战玩家失败")
                errorcode = 101;
            }
            else {
                errorcode = 0;

            }
        }
        if (errorcode != 0) {
            var s2cRoundEndData = {
                errorCode: errorcodet,
                Roundnumber: 0
            }
        } else {
            ++user.roundLevel;
            var s2cRoundEndData = {
                errorCode: errorcodet,
                Roundnumber: user.roundLevel
            }
        }
        var bufEnter = exports.changeType(s2cRoundEnd, s2cRoundEndData);
        var payload = { meesageId: messageEnum.s2cRoundEndMID, data: bufEnter };
        var errMsg = AwesomeMessage.verify(payload);
        if (errMsg)
            throw Error(errMsg);
        var message = AwesomeMessage.create(payload);
        var buf = AwesomeMessage.encode(message).finish();
        if (user && user.socket)
            exports.sendProbufMessage(user.socket, buf);
    }

    exports.changeType = function (type, value) {


        var errMsg = type.verify(value);
        if (errMsg)
            throw Error(errMsg);


        return type.encode(type.create(value)).finish();
    }

    //检测合法性
    function check_account(req) {
        if (req == null)
            return false;
        var account = req.account;
        var sign = req.sign;
        if (account == null || sign == null) {
            return false;
        }

        var serverSign = crypto.md5(account + config.ROOM_PRI_KEY);
        // if (serverSign != sign) {
        //     return false;
        // }
        return true;
    }
    exports.sendProbufMessage = function (ws, msg) {

        ws.send(msg);
    }
    /***检测装扮合法性 */
    function check_dressup(account, req) {
        var sign = req.sign;
        if (account == null || sign == null) {
            return false;
        }

        var serverSign = crypto.md5(account + req.decorateId + req.trailingId + req.userMoney + config.SHOP_PRI_KRY);
        if (serverSign != sign) {
            return false;
        }
        return true;
    }
}
exports.sendBitMessage = function (ws, msg) {
    const buf5 = Buffer.from(JSON.stringify(msg));
    ws.send(buf5);
}
/**随机飞机顺序 */
function plane_order(planes) {
    planes.sort(function () { return 0.5 - Math.random(); });
    return planes;
}
/**随机飞机位置 */
function plane_position(planes) {
    /**存飞机随机位置数组 */
    var position_array = new Array();
    //随机位置
    for (let i = 0; i < planes.length; i++) {
        var position = Math.floor(Math.random() * c_position.length);
        var positionData = {
            positionX: c_position[position].x,
            positionY: c_position[position].y
        }
        position_array.push(positionData);
    }
    return position_array;
}
/**校验发兵金币 */
function checkGold(haveGold, nowGold, sendEnmeys) {
    /**购买飞机的价钱 */
    var enmeysGold = 0;
    for (let q = 0; q < sendEnmeys.length; q++) {
        for (let k = 0; k < c_enmeys.length; k++) {
            if (sendEnmeys[q] == c_enmeys[k].type) {
                enmeysGold += c_enmeys[k].price;
                break;
            }
        }
    }
    if (haveGold - enmeysGold == nowGold) {
        return nowGold;
    } else if (haveGold - enmeysGold <= nowGold) {
        if (haveGold - enmeysGold < 0) {
            return 0;
        } else {
            return haveGold - enmeysGold;
        }
    }
}
/**校验漏兵金币 */
function checkGold_leak(leakEnmeys, allGold, nowGold, oldGold) {
    /**漏掉飞机的价钱 */
    var enmeysGold = 0;
    for (let q = 0; q < leakEnmeys.length; q++) {
        for (let k = 0; k < c_enmeys.length; k++) {
            if (leakEnmeys[q] == c_enmeys[k].type) {
                enmeysGold += c_enmeys[k].getGold;
                break;
            }
        }
    }
    /**如果打掉飞机价钱等于当前金币减去上回合发兵后金币 */
    if ((allGold - enmeysGold) == (nowGold - oldGold)) {
        return nowGold;
    } else if ((allGold - enmeysGold) < (nowGold - oldGold) || (allGold - enmeysGold) > (nowGold - oldGold)) {
        return (allGold - enmeysGold) + oldGold;
    }

}
/**打包消息 */
function send_client_message(protoType, protoData, protoMID) {
    var bufEnter = exports.changeType(protoType, protoData);
    var payload = { meesageId: protoMID, data: bufEnter };
    var errMsg = AwesomeMessage.verify(payload);
    if (errMsg)
        throw Error(errMsg);
    var message = AwesomeMessage.create(payload);
    var buf = AwesomeMessage.encode(message).finish();
    return buf;
}

/**玩家整理 排行榜等 */
function gameloop() {
    //心跳时间间隔
    if (heartCount == 10) {
        exports.ping();
        if (userMgr.viewAllUser() == 0) {
            userid = 33;
        }
        heartCount = 0;
    }
    heartCount++;
    fightRoomMgr.update();

}








/**
 * 每隔3分钟来判断下房间的状态
 */
function roomOpenLoop() {
    //  console.log("清空一次房间");
    //  roomMgr.resetRoom();
}
/**房间对象池等初始化 */





